#include "hal_data.h"
#include <stdio.h>

FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event)
BSP_PLACE_IN_SECTION(".warm_start");
FSP_CPP_FOOTER



#define SHARED_MEMORY_SIZE            (256U)
uint8_t transmit_buffer[SHARED_MEMORY_SIZE]        = {0};
uint8_t receive_buffer[SHARED_MEMORY_SIZE]         = {0};

static volatile uint32_t data_receive_flag = 0;


/*******************************************************************************************************************//**
 * main() is generated by the FSP Configuration editor and is used to generate threads if an RTOS is used.  This function
 * is called by main() when no RTOS is used.
 **********************************************************************************************************************/
void hal_entry(void)
{
#if defined(BSP_MCU_GROUP_RZT2H)
 #if (defined(BSP_CFG_CORE_CR52) && (0 == BSP_CFG_CORE_CR52))

    /* Set "1" to CA550_CTRL. */
    R_MPU_AC->CPU_CTRL |= 0x00000100;
 #endif
#endif

    /* Enable interrupt. */
    __asm volatile ("cpsie i");

    fsp_err_t err;
    shared_memory_status_t status;
    uint32_t offset;

    /* Open the driver. */
    err = R_SHARED_MEMORY_Open(&g_shared_memory0_ctrl, &g_shared_memory0_cfg);
    assert(FSP_SUCCESS == err);



    /* TODO: add your own code here */
    g_cmtw0.p_api->open(g_cmtw0.p_ctrl, g_cmtw0.p_cfg);
    g_cmtw0.p_api->enable(g_cmtw0.p_ctrl);
    g_cmtw0.p_api->start(g_cmtw0.p_ctrl);

    extern void coremain(void);

    coremain();


    uint32_t freq_hz = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_CPU0);
    char freqBuf[50] = {0};
    sprintf(freqBuf, "FSP_PRIV_CLOCK_CPU0=%ld\r\n", freq_hz);
    strcat((char*)transmit_buffer, freqBuf);

    uint32_t transfer_length = SHARED_MEMORY_SIZE / 2;
    /* Write data to the shared memory. */
    offset = 0;
    err = R_SHARED_MEMORY_Write(&g_shared_memory0_ctrl, &(transmit_buffer[0]), offset, transfer_length);
    assert(FSP_SUCCESS == err);

    /* Wait until the driver of CPU1 writes data. */
    //while (0 == data_receive_flag);
    //data_receive_flag = 0;

    while(1)
    {
#if (1 == _RZT_ORDINAL)
        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_19_PIN_6, 0);
        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_19_PIN_4, 0);
#else
        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_20_PIN_0, 0);
        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_23_PIN_4, 0);
#endif
        R_BSP_SoftwareDelay(1000, BSP_DELAY_UNITS_MILLISECONDS);
#if (1 == _RZT_ORDINAL)
        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_19_PIN_6, 1);
        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_19_PIN_4, 1);
#else
        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_20_PIN_0, 1);
        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_23_PIN_4, 1);
#endif
        R_BSP_SoftwareDelay(1000, BSP_DELAY_UNITS_MILLISECONDS);
    }
}

/*******************************************************************************************************************//**
 * This function is called at various points during the startup process.  This implementation uses the event that is
 * called right before main() to set up the pins.
 *
 * @param[in]  event    Where at in the start up process the code is currently at
 **********************************************************************************************************************/
void R_BSP_WarmStart(bsp_warm_start_event_t event)
{
    if (BSP_WARM_START_RESET == event)
    {
        /* Pre clock initialization */
    }

    if (BSP_WARM_START_POST_C == event)
    {
        /* C runtime environment and system clocks are setup. */

#if BSP_FEATURE_DDR_SUPPORTED
  #if (1 == BSP_CFG_DDR_INIT_ENABLE)

       /* Initialize the DDR settings. */
       bsp_ddr_init();
 #endif
#endif

        if (NULL != g_bsp_pin_cfg.p_extend)
        {
            /* Configure pins. */
            R_IOPORT_Open (&g_ioport_ctrl, &g_bsp_pin_cfg);
        }
    }
}

volatile unsigned int coremarkTick;
void g_cmtw0CB(timer_callback_args_t *p_args)
{
    if (TIMER_EVENT_CYCLE_END == p_args->event)
    {
        coremarkTick++;
    }
}

/*******************************************************************************************************************//**
 * This function is user callback function. It is called in the following situations:
 * - When R_SHARED_MEMORY_Open() of the counter driver is called while this driver is open.
 *   In this case, p_args->state is SHARED_MEMORY_STATE_READY_TO_WRITE.
 * - When R_SHARED_MEMORY_Read() of the counter driver is called.
 *   In this case, p_args->state is SHARED_MEMORY_STATE_READY_TO_READ_WRITE.
 *
 * @param[out]  p_args    Callback arguments
 **********************************************************************************************************************/
void shared_memory_callback (shared_memory_callback_args_t * p_args)
{
    if (SHARED_MEMORY_STATE_READY_TO_READ_WRITE == p_args->state)
    {
        data_receive_flag = 1;
    }
    else /* (SHARED_MEMORY_STATE_READY_TO_WRITE == p_args->state) */
    {
        /* do nothing */
    }
}
